<?php
/**
 * Created by PhpStorm.
 * User: Administrator
 * Date: 3/21/2019
 * Time: 5:34 PM
 */

namespace p5\v2\db;


use p5\objects\ArrayUtils;
use p5\objects\SqlMaker;

class SqlTablePart
{
    private $tableName;
    private $tableAiasName = "";
    private $fetchColumns = [];
    private $queryConditions = [];
    private $joinCondition = "";
    private $joinType = "join";

    public function __construct($tableName, $aliasName = "")
    {
        $this->tableName = $tableName;
        $this->tableAiasName = $aliasName;
    }

    public function getSelectColumns()
    {
        $this->formatColumns();
        return implode(",", $this->fetchColumns);
    }

    public function getFromTableName()
    {
        return " " . $this->tableName . " " . $this->getTableAiasName();
    }

    public function getJoinPart()
    {
        return " {$this->joinType} " . $this->tableName . " " . $this->getTableAiasName() . " on " . $this->getJoinCondition();
    }

    public function getConditionPart()
    {
        $this->formatQueryConditions();
        $string = implode(" and ", $this->queryConditions);
        if (empty($string)) {
            return "";
        }
        return "($string)";
    }

    public function addFetchColumns($columns)
    {
        $matrix = ArrayUtils::forceToArray($columns);
        foreach ($matrix as $column) {
            $this->addFetchColumn($column);
        }
    }

    public function addFetchColumn($column)
    {
        // $column = $this->format($column);
        $column = $this->replaceThis($column);
        if (in_array($column, $this->fetchColumns)) {
            return;
        }
        array_push($this->fetchColumns, $column);
    }

    private function formatColumns()
    {
        $size = count($this->fetchColumns);
        for ($i = 0; $i < $size; $i++) {
            $temp = $this->fetchColumns[$i];
            $this->fetchColumns[$i] = $this->format($temp);
        }
    }

    private function formatQueryConditions()
    {
        if (empty($this->tableAiasName)) {
            return;
        }
        for ($i = 0; $i < count($this->queryConditions); $i++) {
            $string = $this->queryConditions[$i];
            $this->queryConditions[$i] = str_replace("{$this->tableName}.", "{$this->tableAiasName}.", $string);
        }
    }

    public function addQueryCondition($condition)
    {
        $condition = $this->replaceThis($condition);
        array_push($this->queryConditions, $condition);
    }

    public function addLike($value, $limits)
    {
        if (empty($value) || empty($limits)) {
            return;
        }
        $value = SqlMaker::sql_safe_replace($value);
        $string = str_replace("{0}", $value, $limits);
        $this->addQueryCondition($string);
    }

    public function addMultiFullLike($value, $columns, $link = " or ")
    {
        if (empty($value) || empty($columns)) {
            return;
        }
        $columns = ArrayUtils::forceToArray($columns);
        $value = SqlMaker::sql_safe_replace($value);
        $list = [];
        foreach ($columns as $column) {
            $column = $this->format($column);
            $segment = "$column like '%{$value}%'";
            array_push($list, $segment);
        }
        $string = implode(" $link ", $list);
        $string = "($string)";
        $this->addQueryCondition($string);
    }

    public function addIn($column, $values, $isStringColumn = false)
    {
        if (empty($column) || empty($values)) {
            return;
        }
        $column = $this->format($column);
        $string = null;
        if (is_string($values)) {
            $string = " $column in ($string)";
        } else if ($isStringColumn === false) {
            $string = implode(",", $values);
            $string = " $column in ($string)";
        } else {
            $string = implode("','", $values);
            $string = " $column in ('$string')";
        }
        $this->addQueryCondition($string);
    }


    private function replaceThis($string)
    {
        return str_replace("this.", $this->getSpaceName() . ".", $string);
    }

    /**
     * 判断是否是复杂的字段，如含有 case , concat format 等
     */
    private static function isComplexColumns($column)
    {
        if (strpos($column, "distinct ") !== false) {
            return true;
        }
        if (strpos($column, "case ") !== false) {
            return true;
        }
        if (strpos($column, "(") !== false) {
            return true;
        }
        return false;
    }

    public function hasAlias(){
        return !empty($this->tableAiasName);
    }

    /**
     * 格式化字段列
     */
    private function format($column)
    {
        if (static::isComplexColumns($column)) {
            return $column;
        }
        // $column = strtolower($column);
        if (strpos($column, ".") === false) {
            $column = $this->getSpaceName() . "." . $column; // 加上表名或者表的别名
        }
        return $column;
    }

    public function getSpaceName()
    {
        if (empty($this->tableAiasName)) {
            return $this->tableName;
        }
        return $this->tableAiasName;
    }

    /**
     * @return string
     */
    public function getTableName()
    {
        return $this->tableName;
    }

    /**
     * @param string $tableName
     */
    public function setTableName($tableName)
    {
        $this->tableName = $tableName;
    }

    /**
     * @return mixed
     */
    public function getTableAiasName()
    {
        if (empty($this->tableAiasName)) {
            return "";
        }
        return $this->tableAiasName;
    }

//    /**
//     * @param mixed $tableAiasName
//     */
//    public function setTableAiasName($tableAiasName)
//    {
//        $this->tableAiasName = $tableAiasName;
//    }

    /**
     * @return array
     */
    public function getFetchColumns()
    {
        return $this->fetchColumns;
    }

    /**
     * @param array $fetchColumns
     */
    public function setFetchColumns($fetchColumns)
    {
        $this->fetchColumns = $fetchColumns;
    }

    /**
     * @return mixed
     */
    public function getJoinCondition()
    {
        return $this->joinCondition;
    }

    /**
     * @param mixed $joinCondition
     */
    public function setJoinCondition($joinCondition)
    {
        $joinCondition = $this->replaceThis($joinCondition);
        $this->joinCondition = $joinCondition;
    }

    /**
     * @return string
     */
    public function getJoinType()
    {
        return $this->joinType;
    }

    /**
     * @param string $joinType
     */
    public function setJoinType($joinType)
    {
        $this->joinType = $joinType;
    }

    public function useLeftJoin()
    {
        $this->setJoinType("left join");
    }

    public function useRightJoin()
    {
        $this->setJoinType("right join");
    }

    /**
     * @return mixed
     */
    public function getQueryConditions()
    {
        return $this->queryConditions;
    }

    /**
     * @param mixed $queryConditions
     */
    public function setQueryConditions($queryConditions)
    {
        $this->queryConditions = $queryConditions;
    }


}